/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ar.com.arkios.kfconTraductor;

import ar.com.arkios.j4d.opException;
import ar.com.arkios.kfcon4d.dao.BultosXEmbaDAO;
import ar.com.arkios.kfcon4d.dao.PalletDAO;
import ar.com.arkios.kfconmodelo.modelo.BultoPorEmbalador;
import ar.com.arkios.kfconmodelo.modelo.MessageReturnOperation;
import ar.com.arkios.kfconmodelo.modelo.Pallet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.log4j.Logger;

/**
 *
 * @author Ale
 * @version 1.01
 * 
 */
public class Main {
    
    /*
    public static void main(String [] args){
        try{
            SAPto4DTransfer aSAPto4DTransfer = new SAPto4DTransfer();
        }catch(Exception ex){
            
        }
    }
    */
    
    private static final String PARAM_DELIM = ":";
    
    private static final String OPCION_DELIM = ";";
    
    private static final Logger logger = Logger.getLogger(Main.class);
    
    private static HashMap<String, Boolean> parametrosMaestros;
    
    private static HashMap<String, Object> parametrosOperativos;
    
    private static HashMap<String, List<String>> parametrosSAP;
    
    private static Set<String> maestrosValidos = getMaestrosValidos();
    
    private static Set<String> operativosValidos = getOperativosValidos();
    
    private static Set<String> sapValidos = getSAPValidos();
    
    
    public static void main(String [] args) {  
        loadParametros(args);
        logger.info("MAIN LANZADO");
/*
        //puse para probar
        try {
            
            if (parametrosMaestros.size() > 0 || parametrosOperativos.size() > 0) {
                SAPTo4DSecondVersion aSAPTo4DSecondVersion = new SAPTo4DSecondVersion();
                for (String maestro : parametrosMaestros.keySet()) {
                    if (maestro.equals(Parametro.MAE_ESPECIE)) {
                        aSAPTo4DSecondVersion.saveEspecies4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_VARIEDAD)) {
                        aSAPTo4DSecondVersion.saveVariedad4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_ENVASE)) {
                        aSAPTo4DSecondVersion.saveEnvases4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_CALIBRE)) {
                        aSAPTo4DSecondVersion.saveCalibres4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_EMBALAJE)) {
                        aSAPTo4DSecondVersion.saveEmbalaje4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_ALMACEN)) {
                        aSAPTo4DSecondVersion.saveAlmacenes4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_CONTRAMARCA)) {
                        aSAPTo4DSecondVersion.saveContramarcas4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_EAN)) {
                        aSAPTo4DSecondVersion.saveEANCodigo4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_ETI)) {
                        aSAPTo4DSecondVersion.saveEtiquetas4D(parametrosMaestros.get(maestro));
                    } else if (maestro.equals(Parametro.MAE_PESO_STANDAR)) {
                        aSAPTo4DSecondVersion.savePesos4d(parametrosMaestros.get(maestro));
                    }
                }   
                for (String maestro : parametrosOperativos.keySet()) {
                    if (maestro.equals(Parametro.OPE_ORDEN)) {
                        aSAPTo4DSecondVersion.saveOrdenes4D();
                    } else if (maestro.equals(Parametro.OPE_LOTE)) {
                        aSAPTo4DSecondVersion.saveLotes4D();
                    }                
                }
            }

            
        } catch (opException ex) {
            logger.error("Excepción 4D: "+ex.getMessage());
        } catch (Exception ex) {
            logger.error("Excepción general : "+ex.getMessage());
        }
        //System.exit(0);
        //logger.info(parametrosOperativos.size());
        //logger.info(parametrosSAP.size());
 */
    }

    public int despachador (String [] args) {
        loadParametros(args);
        logger.info("Despachador lanzado");
        
        try {
            
            if (parametrosMaestros.size() > 0 || parametrosOperativos.size() > 0) {
                MainServer.enviarEstado("Tomando datos de SAP");
                SAPTo4DSecondVersion aSAPTo4DSecondVersion = new SAPTo4DSecondVersion();
                boolean reescritura;
                for (String maestro : parametrosMaestros.keySet()) {
                    if (maestro.equals(Parametro.MAE_ESPECIE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Especies"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveEspecies4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_VARIEDAD)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Variedades"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveVariedad4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_ENVASE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Envases"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveEnvases4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_CALIBRE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Calibres"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveCalibres4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_EMBALAJE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Embalajes"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveEmbalaje4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_ALMACEN)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Almacenes"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveAlmacenes4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_CONTRAMARCA)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Contramarcas"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveContramarcas4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_EAN)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Materiales"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveEANCodigo4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_ETI)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Etiquetas"+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.saveEtiquetas4D(reescritura);
                    } else if (maestro.equals(Parametro.MAE_PESO_STANDAR)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Pesos Std."+(reescritura ? " c/Reesc." : ""));
                        aSAPTo4DSecondVersion.savePesos4d(reescritura);
                    }
                }   
                for (String maestro : parametrosOperativos.keySet()) {
                    if (maestro.equals(Parametro.OPE_ORDEN)) {
                        MainServer.enviarEstado("Actualizando Ordenes de Producción");
                        aSAPTo4DSecondVersion.saveOrdenes4D();
                    } else if (maestro.equals(Parametro.OPE_LOTE)) {
                        MainServer.enviarEstado("Actualizando Lotes de Monte");
                        aSAPTo4DSecondVersion.saveLotes4D();
                    }                
                }
            }
            if (parametrosSAP.size() > 0) {
                List<String> quePallet = parametrosSAP.get("PAL");
                String palletId = "";
                if (quePallet != null) {
                    try {
                        palletId = quePallet.get(0);
                    } catch (IndexOutOfBoundsException e) {
                        logger.error("Error PAL sin nigún palletId");
                    }
                    logger.debug("Inicio subida pallet " + palletId);
                } else {
                    logger.debug("Inicio subida pallet sin id en el comando.");
                }
                MainServer.enviarEstado("Obteniendo datos Pallet");
                PalletDAO pdao = new PalletDAO(MainServer.getMiStoreProc());
                List<Pallet> notif = pdao.getPallet();
                
                MainServer.enviarEstado("Obteniendo datos Cajas");
                BultosXEmbaDAO bxedao = new BultosXEmbaDAO(MainServer.getMiStoreProc());
                List<BultoPorEmbalador> bxe = bxedao.getBxE();
                
                MainServer.enviarEstado("Enviando Pallet a SAP");
                //logger.info("--> Inicio anotación valores para pallet: " + palletId);
                From4DtoSAP tsap = new From4DtoSAP(notif, bxe);
                MessageReturnOperation resultado = tsap.getMyMessageReturnOperation();
                
                String sapMesType = Character.toString(resultado.getMessageType());
                logger.debug("Resulado subida pallet " + palletId + " = '"+ sapMesType + "'");
                MainServer.enviarTexto(sapMesType, "KFSAP_MesType");
                MainServer.enviarTexto(resultado.getMyMessageDesc1(), "KFSAP_Msg1");
                //logger.debug("Resulado Mensaje 1: " + resultado.getMyMessageDesc1());
                MainServer.enviarTexto(resultado.getMyMessageDesc2(), "KFSAP_Msg2");
                //logger.debug("Resulado Mensaje 2: " + resultado.getMyMessageDesc2());
                MainServer.enviarTexto(resultado.getMyMessageDesc3(), "KFSAP_Msg3");
                //logger.debug("Resulado Mensaje 3: " + resultado.getMyMessageDesc3());
                MainServer.enviarTexto(resultado.getMyMessageDesc4(), "KFSAP_Msg4");
                //logger.debug("Resulado Mensaje 4: " + resultado.getMyMessageDesc4());
            }
           
        } catch (opException ex) {
            MainServer.enviarEstado(ex.getMessage());
            logger.error("Excepción 4D: "+ex.getMessage());
            return -1;
        } catch (Exception ex) {
            MainServer.enviarEstado(ex.getMessage());
            logger.error("Excepción general : "+ex.getMessage());
            return -2;
        }
        
        if (parametrosSAP.size() > 0) //si transmiti pallets (nunca transmito junto con maestros u operativos
            return 1;
        else
            return 0;
    }
    
    public int simulador (String [] args) {
        loadParametros(args);
        logger.info("Simulador lanzado");        
        try {
            Thread.sleep(2000);
            boolean reescritura;
            if (parametrosMaestros.size() > 0 || parametrosOperativos.size() > 0) {
                MainServer.enviarEstado("Tomando datos de SAP");
                Thread.sleep(1000);
                for (String maestro : parametrosMaestros.keySet()) {
                    if (maestro.equals(Parametro.MAE_ESPECIE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Especies"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_VARIEDAD)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Variedades"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_ENVASE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Envases"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_CALIBRE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Calibres"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_EMBALAJE)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Embalajes"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_ALMACEN)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Almacenes"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_CONTRAMARCA)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Contramarcas"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_EAN)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Materiales"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_ETI)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Etiquetas"+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    } else if (maestro.equals(Parametro.MAE_PESO_STANDAR)) {
                        reescritura = parametrosMaestros.get(maestro);
                        MainServer.enviarEstado("Actualizando Pesos Std."+(reescritura ? " c/Reesc." : ""));
                        Thread.sleep(1000);
                    }
                }   
                for (String maestro : parametrosOperativos.keySet()) {
                    if (maestro.equals(Parametro.OPE_ORDEN)) {
                        MainServer.enviarEstado("Actualizando Ordenes de Producción");
                        Thread.sleep(3000);
                    } else if (maestro.equals(Parametro.OPE_LOTE)) {
                        MainServer.enviarEstado("Actualizando Lotes de Monte");
                        Thread.sleep(3000);
                    }                
                }
            }
            if (parametrosSAP.size() > 0) {
                List<String> quePallet = parametrosSAP.get("PAL");
                String palletId = "";
                if (quePallet != null) {
                    try {
                        palletId = quePallet.get(0);
                    } catch (IndexOutOfBoundsException e) {
                        logger.error("Error PAL sin nigún palletId");
                    }
                    logger.debug("Inicio subida pallet " + palletId);
                } else {
                    logger.debug("Inicio subida pallet sin id en el comando.");
                }
                MainServer.enviarEstado("Obteniendo datos Pallet");
                Thread.sleep(1000);
                
                MainServer.enviarEstado("Obteniendo datos Cajas");
                Thread.sleep(1000);
                
                MainServer.enviarEstado("Enviando Pallet a SAP");
                Thread.sleep(1000);
                
                String sapMesType = "I";
                logger.debug("Resulado subida pallet " + palletId + " = '"+ sapMesType + "'");
                MainServer.enviarTexto(sapMesType, "KFSAP_MesType");
                MainServer.enviarTexto("Todo Joya 1", "KFSAP_Msg1");
                MainServer.enviarTexto("Todo Joya 2", "KFSAP_Msg2");
                MainServer.enviarTexto("Todo Joya 3", "KFSAP_Msg3");
                MainServer.enviarTexto("Todo Joya 4", "KFSAP_Msg4");
                Thread.sleep(1000);
            }
           
        }/* catch (opException ex) {
            logger.error("Excepción 4D: "+ex.getMessage());
            return -1;
        }*/ catch (Exception ex) {
            logger.error("Excepción general : "+ex.getMessage());
            return -2;
        }
        
        if (parametrosSAP.size() > 0)//si transmiti pallets (nunca transmito junto con maestros u operativos
            return 1;
        else
            return 0;
    }
    
    private static void loadParametros(String[] args) {
        parametrosMaestros = new HashMap<String, Boolean>();
        parametrosOperativos = new HashMap<String, Object>();
        parametrosSAP = new HashMap<String, List<String>>();
        
        // Itero todos los parametrosMaestros pasados por linea de comandos.
        for (String parametro : args) {
            
            parametro = parametro.toUpperCase();
            
            // Verifico si el parametro (comando en principio) tiene algun opción indicada.
            if (isComandoConOpciones(parametro))
            {
                String[] param = parametro.split(PARAM_DELIM);
                
                if (param.length > 2) {
                    logger.info("El parametro " + parametro + " está mal formado. Solo se puede indicar un comando y sus opciones (Ej: <comando>:<opcion1,opcion2,..>");
                    break;
                }
                
                String comando = param[0];
                String opciones = param[1];
                
                cargarComandoConOpciones(comando, opciones);
                
            } else {
                // Si no tiene opciones, valido que sea un parámetro conocido
                // Caso contrario no se tiene en cuenta
                cargarComandoSinOpciones(parametro);
            }
        }
    }
    
    
    private static void cargarComandoConOpciones(String comando, String opciones) {
        // Si el parámetro es uno válido, lo cargo. Caso contrario no hago nada.
        if (isComandoValido(comando)) {
            
            if (isComandoMaestro(comando)) {
                Boolean reescritura = (opciones.equals(Parametro.REESCRITURA)) ? Boolean.TRUE : Boolean.FALSE;
                if (comando.equals(Parametro.MAE_MAESTROS)) {
                    for (String comandoMaestro : Parametro.MAESTROS) {
                        // Si no se indicó el comando por parámetro previamente lo agrago.
                        if (!parametrosMaestros.containsKey(comandoMaestro))
                            parametrosMaestros.put(comandoMaestro, reescritura);
                    }
                } else {
                    parametrosMaestros.put(comando, reescritura);
                }
                
                if (!reescritura) {
                    logger.info("Se indicaron parámetros no válidos para el maestro " + comando + ". Se toma como no reescritura.");
                }
            } else if (isComandoOperativo(comando)) {
                // Hasta el momento no tiene opciones.
                if (comando.equals(Parametro.OPE_OPERATIVOS)) {
                    for (String comandoOperativo : Parametro.OPERATIVOS) {
                        if (!parametrosOperativos.containsKey(comandoOperativo))
                            parametrosOperativos.put(comandoOperativo, null);
                    }
                } else {
                    parametrosOperativos.put(comando, null);
                }
                
                logger.info("Se obtiene el comando " + comando + " ignorando la opción " + opciones);
            } else if (isComandoSAP(comando)) {
                
                // Supongo que las opciones es una lista de IDs.
                List<String> valores = new ArrayList<String>();
                String[] opcionesArray = opciones.split(OPCION_DELIM);
                for (String opcion : opcionesArray) {
                    valores.add(opcion);
                }
                
                if (comando.equals(Parametro.SAP_SAP)) {
                    for (String comandoSAP : Parametro.SAP) {
                        if (!parametrosSAP.containsKey(comandoSAP)) {
                            // TODO: ver que pasa para el parametro PAL que debería ir con opciones.
                            parametrosSAP.put(comandoSAP, valores);
                        }
                    }
                } else {
                    parametrosSAP.put(comando, valores);
                }
                
            } else {
                // En principio ya se valido que el comando sea uno de los tres anteriores pero por las dudas
                logger.info("El comando " + comando + " indicado no es valido. No se tiene en cuenta.");
            }
        } else {
            logger.info("Se recibio el parámetro " + comando + PARAM_DELIM + opciones + " el cual no es reconocido. Se ignora el parámetro.");
        }
    }
    
    private static void cargarComandoSinOpciones(String comando) {
        if (isComandoValido(comando)) {
            if (isComandoMaestro(comando)) {
                Boolean reescritura = Boolean.FALSE;
                
                if (comando.equals(Parametro.MAE_MAESTROS)) {
                    for (String comandoMaestro : Parametro.MAESTROS) {
                        if (!parametrosMaestros.containsKey(comandoMaestro))
                            parametrosMaestros.put(comandoMaestro, reescritura);
                    }
                } else {
                    parametrosMaestros.put(comando, reescritura);
                }
            } else if (isComandoOperativo(comando)) {
                if (comando.equals(Parametro.OPE_OPERATIVOS)) {
                    for (String comandoOperativo : Parametro.OPERATIVOS) {
                        if (!parametrosOperativos.containsKey(comandoOperativo))
                            parametrosOperativos.put(comandoOperativo, null);
                    }
                } else {
                    parametrosOperativos.put(comando, null);
                }
            } else {
                // Esto por ahora queda, pero debería definirse si se puede indicar un comando SAP sin opciones.
                if (comando.equals(Parametro.SAP_SAP)) {
                    for (String comandoSAP : Parametro.SAP) {
                        if(!parametrosSAP.containsKey(comandoSAP))
                            parametrosSAP.put(comandoSAP, null);
                    }
                } else {
                    parametrosSAP.put(comando, null);
                }
            }
        } else {
            logger.info("Se recibio el parámetro " + comando + " el cual no es reconocido. Se ignora el parámetro.");
        }
    }
    
    // Por lo menos el comando debe tener un caracter antes de su delimitador de opciones.
    private static boolean isComandoConOpciones(String parametro) {
        return (parametro.indexOf(PARAM_DELIM) > 0);
    }
    
    private static boolean isComandoValido(String param) {
        return maestrosValidos.contains(param) || sapValidos.contains(param) || operativosValidos.contains(param);
    }
    
    private static boolean isComandoMaestro(String comando) {
        return maestrosValidos.contains(comando);
    }
    
    private static boolean isComandoOperativo(String comando) {
        return operativosValidos.contains(comando);
    }
    
    private static boolean isComandoSAP(String comando) {
        return sapValidos.contains(comando);
    }

    private static Set<String> getMaestrosValidos() {
        Set<String> set = new HashSet<String>();
        
        // Parametros de maestos.
        set.add(Parametro.MAE_MAESTROS);
        set.add(Parametro.MAE_ALMACEN);
        set.add(Parametro.MAE_CALIBRE);
        set.add(Parametro.MAE_CONTRAMARCA);
        set.add(Parametro.MAE_EAN);
        set.add(Parametro.MAE_EMBALAJE);
        set.add(Parametro.MAE_ENVASE);
        set.add(Parametro.MAE_ESPECIE);
        set.add(Parametro.MAE_ETI);
        set.add(Parametro.MAE_PESO_STANDAR);
        set.add(Parametro.MAE_VARIEDAD);
        
        return set;
    }
    
    private static Set<String> getSAPValidos() {
        Set<String> set = new HashSet<String>();
        
        // Parametros de SAP_SAP
        set.add(Parametro.SAP_SAP);
        set.add(Parametro.SAP_BXE);
        set.add(Parametro.SAP_PAL);
        
        return set;
    }
    
    private static Set<String> getOperativosValidos() {
        Set<String> set = new HashSet<String>();
        
        // Parámetros de Operativos
        set.add(Parametro.OPE_LOTE);
        set.add(Parametro.OPE_OPERATIVOS);
        set.add(Parametro.OPE_ORDEN);
        
        return set;
    }

}
